package com.gitee.srurl.core.util.redis;

import com.gitee.srurl.core.util.SpringContextUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;

import java.time.Duration;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zxw
 * @date 2023/4/29 19:50
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class RedisValueUtil<T> {
    private static final RedissonClient redissonClient = SpringContextUtil.getBean(RedissonClient.class);

    public static <T> T get(String key) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.get();
    }

    public static <T> void set(String key, T data) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        bucket.set(data);
    }

    public static <T> void set(String key, T data, long time, TimeUnit timeUnit) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        bucket.set(data, time, timeUnit);
    }

    public static <T> boolean setIfAbsent(String key, T data) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.setIfAbsent(data);
    }

    public static <T> boolean setIfAbsent(String key, T data, Duration duration) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.setIfAbsent(data, duration);
    }

    public static <T> boolean setIfAbsent(String key, T data, long time, TimeUnit timeUnit) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.setIfAbsent(data, Duration.of(time, timeUnit.toChronoUnit()));
    }

    public static <T> boolean setIfExists(String key, T data) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.setIfExists(data);
    }


    public static <T> boolean setIfExists(String key, T data, long time, TimeUnit timeUnit) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.setIfExists(data, time, timeUnit);
    }

    public static <T> T getAndDelete(String key) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.getAndDelete();
    }

    public static <T> boolean delete(String key) {

        RBucket<T> bucket = redissonClient.getBucket(key);
        return bucket.delete();
    }

    /**
     * 获得key剩余存活时间
     *
     * @param key 缓存键值
     * @return 剩余存活时间
     */
    public static <T> long getTimeToLive(final String key) {
        RBucket<T> rBucket = redissonClient.getBucket(key);
        return rBucket.remainTimeToLive();
    }

    /**
     * 设置有效时间
     *
     * @param key      Redis键
     * @param duration 超时时间
     * @return true=设置成功；false=设置失败
     */
    public static <T> boolean expire(final String key, final Duration duration) {
        RBucket<T> rBucket = redissonClient.getBucket(key);
        return rBucket.expire(duration);
    }

    public static <T> boolean exist(final String key) {
        RBucket<T> rBucket = redissonClient.getBucket(key);
        return rBucket.isExists();
    }

    /**
     * 增长1并获取返回值
     */
    public static long incrementAndGet(final String key) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.incrementAndGet();
    }

    /**
     * 减少1并获取返回值
     */
    public static long decrementAndGet(final String key) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.decrementAndGet();
    }

    /**
     * 设置增长数量的初始值
     */
    public static void setAtomicLong(final String key, final long expect) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        atomicLong.set(expect);
    }

    /**
     * 设置增长数量的初始值
     */
    public static long getAtomicLong(final String key) {
        RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
        return atomicLong.get();
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public static Collection<String> keys(final String pattern) {
        Stream<String> stream = redissonClient.getKeys().getKeysStreamByPattern(pattern);
        return stream.collect(Collectors.toList());
    }
}

